/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include "objects.hpp"
#include <GL/gl.h>
#include <GL/glut.h>
#include <cstdio>

#include "picking.hpp"

clickable::clickable()
  :down(false),focused(false)
{
  SetCallback(this);
}

void clickable::Draw()
{
  //printf("clickable: draw\n");
  int mode;
  glGetIntegerv(GL_RENDER_MODE,&mode);
  if (mode==GL_SELECT)
  {
    //select mode drawing
    glRecti(x,y,x+40,y+20);
    //printf("clickable: draw select\n");
  } else {
    //normal drawing
    
    if (focused)
    {
      glColor3f(0,0,1);
      glRecti(x-2,y-2,x+42,y+22);
    }
    
    if (down)
    {
      glColor3f(0,1,0);
    } else {
      glColor3f(0,0.6,0);
    }
    glRecti(x,y,x+40,y+20);
    //printf("clickable: draw normal\n");
  }
}

void clickable::OnFocus(TGLPickEvent event)
{
  //printf("clickable: on focus\n");
  focused=true;
}
    
void clickable::OnFocusLost(TGLPickEvent event)
{
  //printf("clickable: on focus lost\n");
  focused=false;
}


void clickable::OnPick(TGLPickEvent event)
{
  //printf("clickable: on pick\n");
  down=true;
}

void clickable::OnRelease(TGLPickEvent event)
{
  //printf("clickable: on release\n");
  down=false;
}

/*******************************************************/

draggable::draggable()
  :dragged(false)
{
  SetCallback(this);
}

void draggable::Draw()
{
  int mode;

  glGetIntegerv(GL_RENDER_MODE,&mode);
  if (mode==GL_SELECT)
  {
    //select mode drawing
    glRecti(x,y,x+20,y+20);
    //printf("draggable: draw select\n");
  } else {
    //normal drawing
    //printf("draggable: draw normal\n");
    glColor3f(0.3,0,0);
    glRecti(OldX,OldY,OldX+20,OldY+20);
    glColor3f(1,0,0);
    glRecti(x,y,x+20,y+20);
  }
}

void draggable::OnPick(TGLPickEvent event)
{
  //printf("draggable: on pick\n");
  OldX=x;
  OldY=y;
}

void draggable::OnRelease(TGLPickEvent event)
{
  //printf("draggable: on release\n");
  OldX=x;
  OldY=y;
}

void draggable::OnDrag(TGLPickEvent event)
{
  //printf("draggable: on drag\n");
  x=event.GlX-10;
  y=event.GlY-10;
}

/**************************************************/

cube::cube()
{
  SetCallback(this);
  dragging=false;
  focused=false;
}

void cube::Draw()
{
  int mode;
  glGetIntegerv(GL_RENDER_MODE,&mode);
  glPushMatrix();
  if (mode==GL_SELECT)
  {
    glTranslatef(x,y,z);
    glColor3f(1,1,1);
    glutSolidCube(1);
  } else {
    if (dragging)
    {
      glPushMatrix();
      glTranslatef(OldX,OldY,OldZ);
      glColor3f(0,0,1);
      glutWireCube(1);
      glPopMatrix();
    }
    glTranslatef(x,y,z);
    glColor3f(1,1,0);
    glutWireCube(1.01);
    glColor3f(1,0,focused*1.0);
    glutSolidCube(1);
  }
  glPopMatrix();
}

void cube::OnFocus(TGLPickEvent event)
{
  focused=true;
}

void cube::OnFocusLost(TGLPickEvent event)
{
  focused=false;
}

void cube::OnPick(TGLPickEvent event)
{
  OldX=x;
  OldY=y;
  OldZ=z;
  printf("screenx=%d screeny=%d glx=%f gly=%f glz=%f\n",
         event.ScreenX, event.ScreenY, event.GlX, event.GlY, event.GlZ);
  pick=event;
}

void cube::OnRelease(TGLPickEvent event)
{
  OldX=x;
  OldY=y;
  OldZ=z;
  dragging=false;
  
}

void cube::OnDrag(TGLPickEvent event)
{
  dragging=true;
  /*
  x=event.GlX;
  y=event.GlY;
  z=event.GlZ;
  */
  x=OldX+event.GlX-pick.GlX;;
  y=OldY+event.GlY-pick.GlY;;
  z=OldZ+event.GlZ-pick.GlZ;;
}

/******************************************************************************/

/**************************************************/

torus::torus()
{
  SetCallback(this);
  dragging=false;
  focused=false;
}

void torus::Draw()
{
  int mode;
  glGetIntegerv(GL_RENDER_MODE,&mode);
  glPushMatrix();
  if (mode==GL_SELECT)
  {
    glTranslatef(x,y,z);
    glColor3f(1,1,1);
    glutSolidTorus(0.5,1,18,36);
  } else {
    if (dragging)
    {
      glPushMatrix();
      glTranslatef(OldX,OldY,OldZ);
      glColor3f(0,0,1);
      glutWireTorus(0.5,1,18,36);
      glPopMatrix();
    }
    glTranslatef(x,y,z);
    glColor3f(1,1,0);
    glutWireTorus(0.5,1.01,18,36);
    glColor3f(1,0,focused*1.0);
    glutSolidTorus(0.5,1,18,36);
  }
  glPopMatrix();

}

void torus::OnFocus(TGLPickEvent event)
{
  focused=true;
}

void torus::OnFocusLost(TGLPickEvent event)
{
  focused=false;
}

void torus::OnPick(TGLPickEvent event)
{
  OldX=x;
  OldY=y;
  OldZ=z;
  printf("screenx=%d screeny=%d glx=%f gly=%f glz=%f\n",
         event.ScreenX, event.ScreenY, event.GlX, event.GlY, event.GlZ);
  pick=event;
}

void torus::OnRelease(TGLPickEvent event)
{
  OldX=x;
  OldY=y;
  OldZ=z;
  dragging=false;
  
}

void torus::OnDrag(TGLPickEvent event)
{
  dragging=true;
  /*
  x=event.GlX;
  y=event.GlY;
  z=event.GlZ;
  */
  x=OldX+event.GlX-pick.GlX;;
  y=OldY+event.GlY-pick.GlY;;
  z=OldZ+event.GlZ-pick.GlZ;;
}
